var CCEngine = function() {
	var _this = this;

	//画布
	this.canvas;
	this.ctx;
	this.width;
	this.height;
	this.background;

	//实体
	this.entities;
	//粒子
	this.particles;
	//物理实体

	//定时器
	this.timer;

	//鼠标状态
	this.mouse;
	this.mouseDown;
	this.selectedEntity;
	this.accExtra;

	//运行状态
	this.isRunning;
	//是否绘制坐标
	this.drawCoords;
	//粒子效果
	this.createParticle;

	//fps
	this.lastDate;
	this.fps;
	this.showFps;

	//预初始化（画布设置、数据初始化）
	CCEngine.prototype.preInit = function(options) {
		if (options) {
			this.canvas = options.canvas;
			if (this.canvas) {
				this.canvas.width = options.width || 400;
				this.canvas.height = options.height || 400;
				this.width = this.canvas.width;
				this.height = this.canvas.height;
				this.background = options.background || '#fff';
				this.ctx = this.canvas.getContext('2d');

				this.mouse = new CCEngine.Vec2();
				this.mouseDown = false;
				this.selectedEntity = null;
				this.accExtra = new CCEngine.Vec2();
				this.canvas.oncontextmenu = function(e) {
					e.preventDefault();
				};
				this.canvas.onmousemove = function(e) {
					var rect = _this.canvas.getBoundingClientRect();
					_this.mouse.x = e.clientX - rect.left;
					_this.mouse.y = e.clientY - rect.top;
				};
				this.canvas.onmousedown = function(e) {
					_this.mouseDown = true;
					var nearest = _this.nearestEntity();
					if (nearest == _this.selectedEntity)
						_this.selectedEntity = null;
					else
						_this.selectedEntity = nearest;
					paint();
					//console.log("down");
				};
				this.canvas.onmouseup = function(e) {
					_this.mouseDown = false;
					//console.log("up");
				};
				document.onkeydown = function(e) {
					//console.log(e.keyCode);
					switch (e.keyCode) {
						case 87:
							_this.accExtra.y = -0.1;
							break;
						case 83:
							_this.accExtra.y = 0.1;
							break;
						case 65:
							_this.accExtra.x = -0.1;
							break;
						case 68:
							_this.accExtra.x = 0.1;
							break;
					}
				};
				document.onkeyup = function(e) {
					//console.log(e.keyCode);
					switch (e.keyCode) {
						case 87:
							_this.accExtra.y = 0;
							break;
						case 83:
							_this.accExtra.y = 0;
							break;
						case 65:
							_this.accExtra.x = 0;
							break;
						case 68:
							_this.accExtra.x = 0;
							break;
					}
				};
			} else {
				console.log("初始化失败！");
				return null;
			}
			this.isRunning = false;
			this.showFps = options.showFps || false;
			this.drawCoords = options.drawCoords || false;
			this.createParticle = options.createParticle || false;
			this.entities = [];
			this.particles = [];
			console.log("初始化成功！");
		}
		return this;
	};

	//实体初始化
	CCEngine.prototype.init = function(func) {
		func(this.entities);
		console.log("初始化实体完毕，共" + this.entities.length + "个实体");
		paint();
		return this;
	};

	//开始
	CCEngine.prototype.start = function() {
		requestAnimationFrame = window.requestAnimationFrame ||
			window.webkitRequestAnimationFrame ||
			window.msRequestAnimationFrame ||
			window.mozRequestAnimationFrame;
		this.isRunning = true;
		run();
	}

	//停止
	CCEngine.prototype.stop = function() {
		window.cancelAnimationFrame(timer);
		this.isRunning = false;
	}

	CCEngine.prototype.nearestEntity = function() {
		var nearestEn = null;
		var nearestD2 = 999;
		var len = this.entities.length;
		for (var i = 0; i < len; i++) {
			var en = this.entities[i];
			var d2 = en.pos.dist2(this.mouse);
			if ((nearestEn == null || d2 < nearestD2) && d2 < 1000) {
				nearestEn = en;
				nearestD2 = d2;
			}
		}
		return nearestEn;
	}

	//实体运动
	function move() {
		var len = _this.entities.length;
		for (var i = 0; i < len; i++) {
			var entity = _this.entities[i];
			if (!entity.mass) continue;
			var accSum = new CCEngine.Vec2();
			for (var j = 0; j < len; j++) {
				var another = _this.entities[j];
				//过滤小质量（<=MIN_MASS）实体的引力影响
				if (another.mass && another.mass <= CCEngine.MIN_MASS) continue;
				if (another == entity) continue;
				var delta = another.pos.sub(entity.pos);
				var acc = 0;
				if (another.mass)
					acc = another.mass / delta.length2();
				else
					acc = CCEngine.MAX_MASS / delta.length2();
				//console.log(acc);
				var radian = delta.angle();
				if (delta.x > 0 && delta.y < 0) radian = -radian;
				else if (delta.x < 0 && delta.y > 0) radian = Math.PI - radian;
				else if (delta.x < 0 && delta.y < 0) radian = Math.PI + radian;

				accSum.mutableAdd(new CCEngine.Vec2(acc * Math.cos(radian), acc * Math.sin(radian)));
			}

			//添加粒子
			if (_this.createParticle)
				_this.particles.push(new CCEngine.Particle(new CCEngine.Vec2(entity.pos.x, entity.pos.y)));

			//console.log(accSum.x + "   " + accSum.y);
			if (entity == _this.selectedEntity)
				accSum.mutableAdd(_this.accExtra);
			entity.move(accSum);
		}

	}

	//碰撞判定
	function collide() {
		var w = _this.width;
		var h = _this.height;
		var len = _this.entities.length;
		for (var i = 0; i < len; i++) {
			var entity = _this.entities[i];
			if (entity.pos.x < 0 || entity.pos.x > w) {
				entity.pos.x = entity.pos.x < 0 ? 0 : w;
				entity.speed.mutableMul(new CCEngine.Vec2(-0.8, 0.8));
			}
			if (entity.pos.y < 0 || entity.pos.y > h) {
				entity.pos.y = entity.pos.y < 0 ? 0 : h;
				entity.speed.mutableMul(new CCEngine.Vec2(0.8, -0.8));
			}
		}
	}

	//绘制
	function paint() {
		var ctx = _this.ctx;
		//ctx.clearRect(0, 0, _this.width, _this.height)
		ctx.fillStyle = _this.background;
		ctx.fillRect(0, 0, _this.width, _this.height);

		//绘制实体
		var len = _this.entities.length;
		for (var i = 0; i < len; i++) {
			_this.entities[i].draw(ctx, _this.drawCoords);
		}

		//绘制选中实体
		if (_this.selectedEntity) {
			_this.selectedEntity.drawFrame(ctx);
		}

		//绘制粒子
		ctx.fillStyle = "rgba(125,125,125,0.5)";
		for (var j in _this.particles) {
			var particle = _this.particles[j];
			if (particle.life)
				particle.draw(ctx);
			else
				_this.particles.splice(j, 1);
		}

		if (_this.showFps) {
			//console.log(_this.fps);
			ctx.fillStyle = '#888';
			ctx.beginPath();
			ctx.fillText('' + _this.fps, 0, 10);
			ctx.closePath();
			ctx.fill();
		}
	}

	//运行
	function run() {
		if (_this.showFps) {
			var now = new Date().getTime();
			if (_this.lastDate)
				_this.fps = (1000 / (now - _this.lastDate)).toFixed(1);
			_this.lastDate = now;
		}
		//实体运动
		move();
		//碰撞处理
		collide();
		//绘制
		paint();
		timer = requestAnimationFrame(run);
	}

	CCEngine.Vec2 = function(x, y) {
		this.x = x || 0;
		this.y = y || 0;

		CCEngine.Vec2.prototype.add = function(v) {
			return new CCEngine.Vec2(this.x + v.x, this.y + v.y);
		}

		CCEngine.Vec2.prototype.sub = function(v) {
			return new CCEngine.Vec2(this.x - v.x, this.y - v.y);
		}

		CCEngine.Vec2.prototype.mul = function(v) {
			return new CCEngine.Vec2(this.x * v.x, this.y * v.y);
		}

		CCEngine.Vec2.prototype.div = function(v) {
			return new CCEngine.Vec2(this.x / v.x, this.y / v.y);
		}

		CCEngine.Vec2.prototype.mutableSet = function(v) {
			this.x = v.x;
			this.y = v.y;
			return this;
		}

		CCEngine.Vec2.prototype.mutableAdd = function(v) {
			this.x += v.x;
			this.y += v.y;
			return this;
		}

		CCEngine.Vec2.prototype.mutableSub = function(v) {
			this.x -= v.x;
			this.y -= v.y;
			return this;
		}

		CCEngine.Vec2.prototype.mutableMul = function(v) {
			this.x *= v.x;
			this.y *= v.y;
			return this;
		}

		CCEngine.Vec2.prototype.mutableDiv = function(v) {
			this.x /= v.x;
			this.y /= v.y;
			return this;
		}

		CCEngine.Vec2.prototype.length = function() {
			return Math.sqrt(this.length2());
		}

		CCEngine.Vec2.prototype.length2 = function() {
			return this.x * this.x + this.y * this.y;
		}

		CCEngine.Vec2.prototype.dist = function(v) {
			return Math.sqrt(this.dist2(v));
		}

		CCEngine.Vec2.prototype.dist2 = function(v) {
			var deltaX = v.x - this.x;
			var deltaY = v.y - this.y;
			return deltaX * deltaX + deltaY * deltaY;
		}

		CCEngine.Vec2.prototype.angle = function() {
			return Math.atan((this.y * this.y) / (this.x * this.x));
		}

		CCEngine.Vec2.prototype.normal = function() {
			var m = Math.sqrt(this.x * this.x + this.y * this.y);
			return new CCEngine.Vec2(this.x / m, this.y / m);
		}
	}

	CCEngine.Entity = function(pos, speed, radius, mass, color) {
		this.pos = pos || new CCEngine.Vec2();
		this.speed = speed || new CCEngine.Vec2();
		this.acc = new CCEngine.Vec2();
		this.radius = radius || 2;
		this.mass = mass;
		this.color = color || 'rgba(0,0,0,0.8)';

		CCEngine.Entity.prototype.move = function(accV) {
			if (accV.x > 2) accV.x = 2;
			else if (accV.x < -2) accV.x = -2;
			if (accV.y > 2) accV.y = 2;
			else if (accV.y < -2) accV.y = -2;
			this.acc.mutableSet(accV);
			this.speed.mutableAdd(this.acc);
			if (this.speed.x > 6) this.speed.x = 6;
			else if (this.speed.x < -6) this.speed.x = -6;
			if (this.speed.y > 6) this.speed.y = 6;
			else if (this.speed.y < -6) this.speed.y = -6;
			this.pos.mutableAdd(this.speed);
		}

		CCEngine.Entity.prototype.draw = function(ctx, drawCoords) {
			ctx.fillStyle = this.color;
			ctx.beginPath();
			ctx.arc(this.pos.x, this.pos.y, this.radius, 0, 2 * Math.PI);
			ctx.closePath();
			ctx.fill();
			if (drawCoords) {
				ctx.fillText('-(' + this.pos.x.toFixed(0) + ',' + this.pos.y.toFixed(0) + ')', this.pos.x + 4, this.pos.y);
			}
		}

		CCEngine.Entity.prototype.drawFrame = function(ctx) {
			//ctx.strokeStyle = "rgba(80,50,50,0.5)";
			ctx.strokeStyle=this.color;
			ctx.fillStyle = this.color;
			ctx.lineWidth = 1;

			//绘制外圆环
			ctx.beginPath();
			ctx.arc(this.pos.x, this.pos.y, this.radius + 2, 0, 2 * Math.PI);
			ctx.closePath();
			ctx.stroke()

			/*//绘制速度方向
			ctx.beginPath();
			ctx.moveTo(this.pos.x, this.pos.y);
			ctx.lineTo(this.pos.x + this.speed.x * 4, this.pos.y + this.speed.y * 4);
			ctx.closePath();
			ctx.stroke();

			//绘制加速度方向
			ctx.beginPath();
			ctx.moveTo(this.pos.x, this.pos.y);
			var nomal = this.acc.normal();
			ctx.lineTo(this.pos.x + nomal.x * 10, this.pos.y + nomal.y * 10);
			ctx.closePath();
			ctx.stroke();*/

			//绘制速度加速度方向
			var nomal = this.acc.normal();
			ctx.beginPath();
			ctx.moveTo(this.pos.x + this.speed.x * 4, this.pos.y + this.speed.y * 4);
			ctx.lineTo(this.pos.x, this.pos.y);
			ctx.lineTo(this.pos.x + nomal.x * 10, this.pos.y + nomal.y * 10);
			//ctx.closePath();
			ctx.stroke();

			//绘制文字信息
			ctx.fillText('-speed(' + this.speed.x.toFixed(2) + ',' + this.speed.y.toFixed(2) + ')', this.pos.x + 4, this.pos.y + 10);
			ctx.fillText('-acc(' + this.acc.x.toFixed(4) + ',' + this.acc.y.toFixed(4) + ')', this.pos.x + 4, this.pos.y + 20);
			ctx.fillText('-mass(' + (this.mass ? this.mass.toFixed(2) : 'infinity') + ')', this.pos.x + 4, this.pos.y + 30);
		}
	}

	CCEngine.Particle = function(pos, life) {
		this.pos = pos || new CCEngine.Vec2();
		this.life = (life === 0 ? 0 : life) || 5;

		CCEngine.Particle.prototype.draw = function(ctx) {
			if (!life === true)
				this.life -= 1;
			this.pos.x += Math.random() * 4 - 2;
			this.pos.y += Math.random() * 4 - 2;
			ctx.beginPath();
			ctx.arc(this.pos.x << 0, this.pos.y << 0, 0.5 + Math.random(), 0, 2 * Math.PI);
			ctx.closePath();
			ctx.fill();
		}
	}

	CCEngine.MIN_MASS = 1;
	CCEngine.MAX_MASS = 999;

	CCEngine.COLORS = [
		'rgba(21,44,94,1.0)',
		'rgba(63,94,161,1.0)',
		'rgba(138,171,242,1.0)',
		'rgba(204,214,235,1.0)',
		'rgba(173,183,204,1.0)',
	];

	CCEngine.COLORS2 = [
		'rgba(234,211,161,1.0)',
		'rgba(192,161,94,1.0)',
		'rgba(117,84,13,1.0)',
		'rgba(51,41,20,1.0)',
		'rgba(82,72,51,1.0)',
	];

	CCEngine.ranColor = function(arrColor) {
		var arr = arrColor || CCEngine.COLORS;
		return arr[Math.floor(Math.random() * arr.length)];
	};

	CCEngine.ranVec2 = function(x, y) {
		var maxX = x || _this.canvas.width;
		var maxY = y || _this.canvas.height;
		return new CCEngine.Vec2(Math.random() * maxX, Math.random() * maxY);
	};

	CCEngine.ran = function(min, max, floor) {
		var range = max - min;
		var n = (min + Math.random() * range);
		if (floor) n = Math.floor(n);
		return n;
	};
}